import * as THREE from 'three';
import dat from 'dat.gui';
import {
  initStats,
  initRenderer,
  initCamera,
  addDefaultCubeAndSphere,
  addGroundPlane
} from '../util';

export function init02(width, height) {
  // 初始化性能统计
  const stats = initStats();
  // 初始化渲染器
  const renderer = initRenderer(width, height);
  // 初始化相机
  const camera = initCamera(width, height);
  // 创建场景
  const scene = new THREE.Scene();

  // 相机、灯光、对象
  const cubeAndSphere = addDefaultCubeAndSphere(scene);
  const cube = cubeAndSphere.cube;
  const sphere = cubeAndSphere.sphere;
  // 地面
  const plane = addGroundPlane(scene);

  // 添加环境光源
  const ambientColor = 0x1c1c1c;
  const ambientLight = new THREE.AmbientLight(ambientColor);
  scene.add(ambientLight);

  // 添加聚光灯
  const spotLight0 = new THREE.SpotLight(0xcccccc);
  spotLight0.position.set(-40, -30, -10);
  spotLight0.lookAt(plane);
  scene.add(spotLight0);

  // 添加光源目标
  const target = new THREE.Object3D();
  target.position.set(5, 0, 0);

  // 添加光源
  const spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-40, 60, -10);
  spotLight.castShadow = true;
  spotLight.shadow.camera.near = 1;
  spotLight.shadow.camera.far = 100;
  spotLight.shadow.camera.fov = 120;
  spotLight.target = plane;
  spotLight.distance = 0;
  spotLight.angle = 0.4;
  scene.add(spotLight);

  // 照相机辅助助手
  const cameraHelper = new THREE.CameraHelper(spotLight.shadow.camera);

  const lightHelper = new THREE.SpotLightHelper(spotLight);
  scene.add(lightHelper);

  // 添加一个模拟点光源的小球体;
  const sphereLight = new THREE.SphereGeometry(0.2);
  const sphereLightMaterial = new THREE.MeshBasicMaterial({
    color: 0xac6c25
  });
  const sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
  sphereLightMesh.castShadow = true;
  sphereLightMesh.position.set(3, 20, 3);
  scene.add(sphereLightMesh);

  // 安装变量控制器

  let step = 0;
  let invert = 1;
  let phase = 0;

  const controls = stepControls();

  // 渲染
  render();

  function render() {
    stats.update();
    // 围绕它的轴旋转立方体
    cube.rotation.x += controls.rotationSpeed;
    cube.rotation.y += controls.rotationSpeed;
    cube.rotation.z += controls.rotationSpeed;

    // 使球体上下弹跳
    step += controls.bouncingSpeed;
    sphere.position.x = 20 + 10 * Math.cos(step);
    sphere.position.y = 2 + 10 * Math.abs(Math.sin(step));

    // 模拟移动灯光
    if (!controls.stopMovingLight) {
      if (phase > 2 * Math.PI) {
        invert = invert * -1;
        phase -= 2 * Math.PI;
      } else {
        phase += controls.rotationSpeed;
      }
      sphereLightMesh.position.z = +(7 * Math.sin(phase));
      sphereLightMesh.position.x = +(14 * Math.cos(phase));
      sphereLightMesh.position.y = 15;

      if (invert < 0) {
        var pivot = 14;
        sphereLightMesh.position.x =
          invert * (sphereLightMesh.position.x - pivot) + pivot;
      }
      spotLight.position.copy(sphereLightMesh.position);
    }
    lightHelper.update();
    renderer.render(scene, camera);
    requestAnimationFrame(render);
  }

  function stepControls() {
    const controls = {
      rotationSpeed: 0.03,
      bouncingSpeed: 0.03,
      ambientColor: ambientColor,
      pointColor: spotLight.color.getStyle(),
      intensity: 1,
      distance: 0,
      angle: 0.1,
      shadowDebug: false,
      castShadow: true,
      target: 'Plane',
      stopMovingLight: false,
      penumbra: 0
    };

    const gui = new dat.GUI();
    gui.addColor(controls, 'ambientColor').onChange(function(e) {
      ambientLight.color = new THREE.Color(e);
    });

    gui.addColor(controls, 'pointColor').onChange(function(e) {
      spotLight.color = new THREE.Color(e);
    });

    gui.add(controls, 'angle', 0, Math.PI * 2).onChange(function(e) {
      spotLight.angle = e;
    });

    gui.add(controls, 'intensity', 0, 5).onChange(function(e) {
      spotLight.intensity = e;
    });

    gui.add(controls, 'penumbra', 0, 1).onChange(function(e) {
      spotLight.penumbra = e;
    });

    gui.add(controls, 'distance', 0, 200).onChange(function(e) {
      spotLight.distance = e;
    });

    gui.add(controls, 'shadowDebug').onChange(function(e) {
      if (e) {
        scene.add(cameraHelper);
      } else {
        scene.remove(cameraHelper);
      }
    });

    gui.add(controls, 'castShadow').onChange(function(e) {
      spotLight.castShadow = e;
    });

    gui
      .add(controls, 'target', ['Plane', 'Sphere', 'Cube'])
      .onChange(function(e) {
        switch (e) {
          case 'Plane':
            spotLight.target = plane;
            break;
          case 'Sphere':
            spotLight.target = sphere;
            break;
          case 'Cube':
            spotLight.target = cube;
            break;
        }
      });

    gui.add(controls, 'stopMovingLight').onChange(function(e) {
      controls.stopMovingLight = e;
    });

    return controls;
  }
}
